package com.springboot.service.impl;

import com.alibaba.fastjson.JSON;
import com.springboot.constant.AdministratorExecl;
import com.springboot.constant.HealthRecordExecl;
import com.springboot.dto.AdministratorDTO;
import com.springboot.dto.EditPasswordDTO;
import com.springboot.dto.PopulationDTO;
import com.springboot.entity.Administrator;
import com.springboot.entity.HealthRecord;
import com.springboot.entity.WxUser;
import com.springboot.enums.ErrorEnum;
import com.springboot.enums.WxUserStatus;
import com.springboot.exception.MyException;
import com.springboot.repository.AdministratorRepository;
import com.springboot.repository.HealthRecordRepositiry;
import com.springboot.repository.WxUserRepository;
import com.springboot.service.AdministratorService;
import com.springboot.utils.CopyObjectUtil;
import com.springboot.utils.DateUtil;
import com.springboot.utils.ExeclUtil;
import com.springboot.utils.UserUtil;
import com.springboot.vo.AdminIndexVO;
import com.springboot.vo.PageVO;
import com.sun.corba.se.spi.copyobject.CopyobjectDefaults;
import com.sun.org.apache.bcel.internal.generic.POP;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.concurrent.CompletableToListenableFutureAdapter;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.Predicate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: lzh
 */
@Service
public class AdministratorServiceImpl implements AdministratorService {

    @Autowired
    WxUserRepository wxUserRepository;

    @Autowired
    private EntityManager entityManager;

    @Autowired
    HealthRecordRepositiry healthRecordRepositiry;

    @Autowired
    AdministratorRepository administratorRepository;


    @Override
    public AdminIndexVO getIndex() {
        //查询小区人数
        AdminIndexVO adminIndexVO = new AdminIndexVO();
        List<WxUser> wxUserList = wxUserRepository.findAll();
        long total = wxUserList.stream().filter(WxUser::getIsRegident).count();
        adminIndexVO.setTotal(total);
        //查询体温预警人数
        long healthy = wxUserList.stream()
                .filter(u -> u.getStatus().equals(WxUserStatus.HEALTHY.getMsg())).count();
        long attention = wxUserList.stream()
                .filter(u -> u.getStatus().equals(WxUserStatus.ATTENTION.getMsg())).count();
        long sick = wxUserList.stream()
                .filter(u -> u.getStatus().equals(WxUserStatus.SICK.getMsg())).count();
        adminIndexVO.setAtention(attention);
        //查询今日进入人次
        Integer entry = healthRecordRepositiry.findByTimeBetween(DateUtil.initDateByDay(), new Date()).size();
        adminIndexVO.setEntry(entry);
        //查询近七天人口流动
        String sql = "select count(*) as val, DATE_FORMAT(h.time, '%Y-%m-%d') as date from health_record as h " +
                "where DATE_SUB(CURDATE(), INTERVAL 7 DAY) < h.time GROUP BY date ORDER BY date";
        int week = -7;
        int i = 0;
        List<PopulationDTO> population = new ArrayList<>(7);
        List list = entityManager.createNativeQuery(sql).getResultList();
        while (week <= -1) {
            PopulationDTO populationDTO = new PopulationDTO();
            populationDTO.setDate(DateUtil.getDateStringByNum(week++));
            if(i < list.size()) {
                Object[] o1 = (Object[]) list.get(i);
                if (o1[1].toString().equals(populationDTO.getDate())) {
                    populationDTO.setVal(o1[0].toString());
                    i++;
                } else {
                    populationDTO.setVal("0");
                }
            }
            population.add(populationDTO);
        }
        adminIndexVO.setPopulation(population);
        //查询用户健康分布
        ArrayList<Long> status = new ArrayList<>();
        status.add(healthy);
        status.add(attention);
        status.add(sick);
        adminIndexVO.setStatus(status);
        return adminIndexVO;
    }

    @Override
    public PageVO getAdminList(Integer pageNum, Integer pageSize, String keywords) {
        Page<Administrator> page = administratorRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
            Predicate username = null;
            if (keywords != null) {
                username = criteriaBuilder.like(root.get("username"), "%" + keywords + "%");
            }
            return criteriaBuilder.and(username);
        }, PageRequest.of(pageNum - 1, pageSize));
        PageVO pageVO = PageVO.convert(page);
        return pageVO;
    }

    @Override
    public void addAdmin(AdministratorDTO administratorDTO) {
        Administrator byUsername = administratorRepository.findByUsername(administratorDTO.getUsername());
        if (byUsername != null) {
            throw new MyException(ErrorEnum.ADMINISTRATOR_EXIST);
        }
        Administrator administrator = new Administrator();
        BeanUtils.copyProperties(administratorDTO, administrator);
        String password = new BCryptPasswordEncoder().encode(administratorDTO.getPassword());
        administrator.setPassword(password);
        administratorRepository.save(administrator);
    }

    @Override
    public void deleteAdmin(Integer id) {
        if (id == 1) {
            throw new MyException(ErrorEnum.DELETE_ADMINISTRATOR_ERROR);
        }
        administratorRepository.deleteById(id);
    }

    @Override
    public HSSFWorkbook dowloadExecl() {
        List<Administrator> administratorList = administratorRepository.findAll();
        List<List<String>> values = new ArrayList<>();
        for (Administrator administrator : administratorList) {
            List<String> value = new ArrayList<>();
            value.add(administrator.getUsername());
            value.add(administrator.getIsSuper() ? "超级管理员" : "普通管理员");
            values.add(value);
        }
        return ExeclUtil.getHSSFWorkbook(AdministratorExecl.SHEETNAME
                , AdministratorExecl.TITLES, values);
    }

    @Override
    public void setSuperAdmin(Integer id) {
        if (id == 1) {
            throw new MyException(ErrorEnum.EDIT_ADMINISTRATOR_ERROR);
        }
        Administrator administrator = administratorRepository.getOne(id);
        administrator.setIsSuper(!administrator.getIsSuper());
        administratorRepository.save(administrator);
    }

    @Override
    public void editPassword(EditPasswordDTO editPasswordDTO) {
        Administrator administrator = UserUtil.getCurrentAdmin();
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(editPasswordDTO.getCurrent(), administrator.getPassword())) {
            throw new MyException(ErrorEnum.EDIT_PASSWORD_ERROR);
        }
        administrator.setPassword(encoder.encode(editPasswordDTO.getAfter()));
        administratorRepository.save(administrator);
    }
}
